import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;

import java.time.Instant;

public class CodeGeneratorTest {
  
    private static final String REDIS_KEY = "coupon:counter";  

    // 假设我们希望每毫秒最多生成1000个优惠券编码（这在实际中可能不现实，但用于示例）  
    private static final int MAX_PER_MILLISECOND = 1000;  
    private static final long OFFSET_BASE = 1000; // 用于将时间戳部分转换为0-999的偏移量  
  
    public static String generateCouponCode() {  
        // 使用INCRBY生成一个唯一的序列号（这里假设它不会在短时间内溢出）  
        long sequence = 10L;
  
        // 获取当前时间戳的毫秒级后三位（注意：这可能会重复，但概率较低）  
        long currentTimeMillis = Instant.now().toEpochMilli();
        System.out.println(currentTimeMillis);
        int millisOffset = (int) (currentTimeMillis % 10000000); // 取毫秒级的后三位
        System.out.println(millisOffset);
        System.out.println(millisOffset * OFFSET_BASE);
  
        // 为了避免在同一毫秒内生成超过1000个编码，我们可以将序列号与OFFSET_BASE结合使用  
        // 这里简单地将序列号对MAX_PER_MILLISECOND取模，然后与millisOffset结合  
        // 注意：这种方法在高并发下仍然有重复的风险，但风险较低
        long i = sequence % MAX_PER_MILLISECOND;
        System.out.println(i);
        long combinedOffset =  Long.parseLong(i + ""+ millisOffset * OFFSET_BASE);
        System.out.println(combinedOffset);
  
        // 由于我们只需要12位数字，并且已经有一个序列号作为基础，  
        // 我们可能不需要完整的combinedOffset，而是将其用作调整序列号的因子  
        // 但为了简化示例，我们直接将其与序列号结合（这可能会导致超过12位）  
        // 在实际中，你可能需要更复杂的逻辑来确保编码长度  
  
        // 这里我们假设序列号足够小，可以直接与combinedOffset相加而不超过12位  
        // 如果不是，你可能需要截断序列号或使用其他方法来确保总长度  
  
        // 注意：以下代码可能生成超过12位的数字，仅用于示例  
        long couponNumber = sequence * 100000000000L + combinedOffset; // 假设BASE为100000000000以确保长度  
  
        // 如果需要严格12位，你可能需要截断或重新计算couponNumber  
        // 但由于我们使用了基于时间的偏移量，直接截断可能会导致冲突  
        // 因此，在实际应用中，你应该设计一个更安全的算法  
  
        // 这里我们仅模拟生成过程，并不真正截断  
        String couponCode = String.valueOf(couponNumber);  
  
        // 如果需要，可以在这里添加截断逻辑，但请注意这可能会增加冲突的风险  
  
        // 返回优惠券编码（注意：这里返回的可能是超过12位的数字）  
        return couponCode.substring(0, Math.min(couponCode.length(), 12));  
  
        // 注意：上面的截断方式在并发环境下是不安全的，因为它可能导致重复的编码  
        // 在实际应用中，你应该使用更复杂的逻辑来确保编码的唯一性和长度  
    }

    public static void main(String[] args) {
        //System.out.println(CodeGeneratorTest.generateCouponCode());

        Snowflake snowflake = IdUtil.getSnowflake(1L, 1L);
        System.out.println(snowflake.nextId());
        System.out.println(2L & 4095L | 2 | 4);


    }
}